package cn.lisens.jpa.web;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    /**
     * 全局拦截 Controller中@RequestBody的DTO的Json数据校验
     * @param ex
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public String handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        
        ex.getBindingResult().getAllErrors().forEach(error -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });
        return errors.toString();
    }
    
    /**
     * 全局拦截 Controller类被@Validate修饰后，在方法的参数前面直接修饰校验规则
     * @param ex
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public String handleValidationExceptions(ConstraintViolationException ex) {
        Map<String, String> errors = new HashMap<>();
        errors = ex.getConstraintViolations()
	            .stream()
	            .collect(Collectors.toMap(
	                violation -> violation.getPropertyPath().toString(),
	                ConstraintViolation::getMessage
	            ));
        
        return errors.toString();
    }
    
    /**
     * 全局拦截通过url的query参数或者form-data提交的数据校验
     * @param ex
     * @return
     */
    @ExceptionHandler(BindException.class)
    public String handleValidationExceptions(BindException ex) {
    	Map<String, String> errors = ex.getBindingResult().getFieldErrors()
    		    .stream()
    		    .collect(Collectors.toMap(
    		        FieldError::getField,
    		        fieldError -> fieldError.getDefaultMessage() != null ? fieldError.getDefaultMessage() : "Invalid value",
    		        (existingMessage, newMessage) -> existingMessage + "; " + newMessage // 合并策略
    		    ));
        return errors.toString();
        
    }
}